home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AM/FM: Amiga Musicians' Freeware Magazine 1
/
AM-FM 1.adf
/
TechCorner
/
midiroutines.a
< prev
next >
Wrap
Text File
|
1991-10-03
|
5KB
|
245 lines
; Routines for sending/receiving MIDI data to/from the serial port
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Written by Teijo Kinnunen.
; For a complete description of these routines, see the
; accompanying text file.
; Please feel free to use these routines in your own programs!!
; If you want to install the input handler, set INPUT to 1.
INPUT EQU 0
; These XDEFs allow you to link e.g. with C-programs.
XDEF _GetSerial
XDEF _FreeSerial
XDEF _AddMIDIData
XDEF _ResetMIDI
CODE ;some assemblers require SECTION
_GetSerial: move.l a6,-(sp)
bsr.s GetSer
tst.l d0
beq.s GSerial_exit
movea.l 4,a6
jsr -$84(a6) ;Forbid()
lea $15e(a6),a0
lea serdevname(pc),a1
jsr -$114(a6) ;FindName()
tst.l d0
beq.s GSerial_nosd
move.l d0,a1
jsr -$1b6(a6) ;RemDevice()
GSerial_nosd jsr -$8a(a6) ;Permit()
bsr.s GetSer
GSerial_exit move.l (sp)+,a6
rts
GetSer: move.l a6,-(sp)
movea.l 4,a6
moveq #0,d0
lea miscresname(pc),a1
jsr -$1f2(a6)
tst.l d0
beq.s GS_error
move.l d0,miscresbase
move.l d0,a6
moveq #0,d0
lea myname(pc),a1
jsr -$6(a6) ;AllocMiscResource()
tst.l d0
bne.s GS_error
st serportalloc
;It's usually required to call _InitSerial only once, so it's
;convenient to do it now.
bsr.s _InitSerial
moveq #0,d0
GS_exit move.l (sp)+,a6
rts
GS_error moveq #-1,d0
bra.s GS_exit
_InitSerial move.l a6,-(sp)
move.b serportalloc(pc),d0
beq.s InitSer_exit
move.w #114,$dff032 ;$dff032 = SERPER
moveq #0,d0
lea tbeinterrupt(pc),a1
movea.l 4,a6
jsr -$a2(a6) ;SetIntVector()
move.l d0,prevtbe
IFNE INPUT
moveq #11,d0
lea rbfinterrupt(pc),a1
jsr -$a2(a6) ;SetIntVector()
move.l d0,prevrbf
move.w #$8801,$dff09a
ELSEIF
move.w #$8001,$dff09a
ENDC
InitSer_exit move.l (sp)+,a6
rts
SerIntHandler: move.w #$4000,$9a(a0) ;$dff09a = INTENA
addq.b #1,$126(a6) ;ExecBase->IDNestCnt
move.w #1,$9c(a0) ;$dff09c = INTREQ
move.b bytesinbuff(pc),d0
beq.s SerInt_bufempty
movea.l 4(a1),a5
move.w #$100,d1
move.b (a5)+,d1
move.w d1,$30(a0) ;$dff030 = SERDAT
cmpa.l a1,a5
bne.s SerInt_resrp
lea sendbuffer(pc),a5
SerInt_resrp subq.b #1,d0
move.b d0,8(a1)
move.l a5,4(a1)
SerInt_exit subq.b #1,$126(a6)
bge.s SerInt_X
move.w #$c000,$9a(a0)
SerInt_X rts
SerInt_bufempty st 9(a1)
bra.s SerInt_exit
_AddMIDIData: move.b serportalloc(pc),d1
beq.s AMD_rts
movem.l a2/a6,-(sp)
movea.l 4,a6
move.w #$4000,$dff09a
addq.b #1,$126(a6)
lea buffptr(pc),a2
tst.b 9(a2)
beq.s AMD_noTBEreq
clr.b 9(a2)
move.w #$8001,$dff09c
AMD_noTBEreq movea.l (a2),a1
AMD_dataloop move.b (a0)+,d1
bpl.s AMD_nostatus
cmp.b #$ef,d1
bhi.s AMD_nostatus
cmp.b lastcmdbyte(pc),d1
beq.s AMD_noinsbyte
move.b d1,10(a2)
AMD_nostatus move.b d1,(a1)+
addq.b #1,8(a2)
AMD_noinsbyte cmpa.l a2,a1
bne.s AMD_noptrreset
lea sendbuffer(pc),a1
AMD_noptrreset subq.b #1,d0
bne.s AMD_dataloop
move.l a1,(a2)
subq.b #1,$126(a6)
bge.s AMD_x
move.w #$c000,$dff09a
AMD_x movem.l (sp)+,a2/a6
AMD_rts rts
_ResetMIDI: move.l a6,-(sp)
movea.l 4,a6
move.w #$4000,$dff09a
addq.b #1,$126(a6)
lea buffptr(pc),a1
lea sendbuffer(pc),a0
move.l a0,(a1)+
move.l a0,(a1)+
clr.b (a1)+
addq.l #1,a1
clr.b (a1)
subq.b #1,$126(a6)
bge.s ResetM_x
move.w #$c000,$dff09a
ResetM_x move.l (sp)+,a6
rts
IFNE INPUT
XREF _maintsk ;the task to be signalled
XREF _sigmask ;the signal mask
XREF _inputbuff ;a 3-byte input note buffer
RBFIntHandler: move.w $18(a0),d0 ;$dff018 = SERDATR
move.w #$0800,$9c(a0)
tst.b d0
bpl.s RBF_nostatus
cmp.b #$f7,d0
bhi.s RBF_exit
move.b d0,(a1)
clr.b 3(a1)
RBF_exit rts
RBF_nostatus moveq #0,d1
move.b 3(a1),d1
move.b d0,1(a1,d1.w)
addq.b #1,d1
cmp.b #2,d1
bge.s RBF_signal
move.b d1,3(a1)
rts
RBF_signal clr.b 3(a1)
move.b (a1),d0
and.b #$f0,d0
cmp.b #$90,d0
beq.s RBF_sig
cmp.b #$80,d0
bne.s RBF_nosig
RBF_sig lea _inputbuff,a0
move.b (a1)+,(a0)+
move.b (a1)+,(a0)+
move.b (a1),(a0)
movea.l _maintsk,a1
move.l _sigmask,d0
jsr -$144(a6) ;Signal()
RBF_nosig rts
ENDC
_FreeSerial: move.l a6,-(sp)
tst.b serportalloc
beq.s FreeSer_xit
move.w #$0801,$dff09a
movea.l 4,a6
moveq #0,d0
move.l prevtbe(pc),a1
jsr -$a2(a6) ;SetIntVector()
IFNE INPUT
moveq #11,d0
move.l prevrbf(pc),a1
jsr -$a2(a6) ;SetIntVector()
ENDC
movea.l miscresbase(pc),a6
moveq #0,d0
jsr -$c(a6) ;FreeMiscResource()
clr.b serportalloc
FreeSer_xit move.l (sp)+,a6
rts
;DON'T CHANGE THE ORDER OF THESE 6 ENTRIES
sendbuffer ds.b 128
buffptr dc.l sendbuffer ;buffer WRITE pointer
readbuffptr dc.l sendbuffer ;buffer READ pointer
bytesinbuff dc.b 0
bufferempty dc.b -1
lastcmdbyte dc.b 0
miscresname dc.b 'misc.resource',0
serportalloc dc.b 0
;USE THE NAME OF YOUR OWN PROGRAM INSTEAD OF 'MyProggie'
myname dc.b 'MyProggie',0
tbename dc.b 'MyProggie serial interrupt',0
serdevname dc.b 'serial.device',0
even
miscresbase dc.l 0
prevtbe dc.l 0
tbeinterrupt dc.w 0,0,0,0,0
dc.l tbename,buffptr,SerIntHandler
IFNE INPUT
recmidi dc.b 0,0,0,0
prevrbf dc.l 0
rbfinterrupt dc.w 0,0,0,0,0
dc.l rbfname,recmidi,RBFIntHandler
rbfname dc.b 'MyProggie RBF-interrupt',0
ENDC
END